package BussinessLayer;

import DTO.Member.Members;
import DTO.Report.Reports;
import DTO.Rule.RuleList;
import DTO.Rule.Rules;
import DataAccessLayer.ReportsSql;
import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

public class ReportsFactory {

    ReportsSql _dataObject = null;

    public ReportsFactory() {
        _dataObject = new ReportsSql();
    }

    public Boolean Insert(Reports businessObject) {
        return _dataObject.Insert(businessObject);
    }

    public Boolean Update(Reports businessObject) {
        return _dataObject.Update(businessObject);
    }

    public Reports GetByPrimaryKey(int keys) {
        return _dataObject.SelectByPrimaryKey(keys);
    }

    public List<Reports> GetAll() {
        return _dataObject.SelectAll();
    }

    public List<Reports> GetAllBy(Reports.ReportsFields fieldName, Object value) {
        return _dataObject.SelectByField(fieldName.toString(), value);
    }

    public static void ComputeComission(Members member) {
        String[] strParentList = member.getNameSpace().trim().split("\\.");
        int iLenghtOflist = strParentList.length - 2;

        //RulesFactory ruleFactory = new RulesFactory();
        MembersFactory memberFactory = new MembersFactory();
        ReportsFactory reportsFactory = new ReportsFactory();

        try {
            //Declare levels and get define value of each levels in database
            int ilevels = 1;
            List<Rules> ruleList = new ArrayList<Rules>();
            //RuleList rules = new RuleList();
            JAXBContext jc = JAXBContext.newInstance(RuleList.class);
            Unmarshaller u = jc.createUnmarshaller();
            File f = new File("rules.xml");
            // JAXBElement tmp = (JAXBElement) u.unmarshal(f);
            //MemberList item = (MemberList) tmp.getValue();
            RuleList rules = (RuleList) u.unmarshal(f);
            ruleList = rules.getRule();
            //Do while for compute Comission for all parent of this members
            while (iLenghtOflist <= 8 && iLenghtOflist >= 0) {
                //get memID of parent  level i
                int memID = Integer.parseInt(strParentList[iLenghtOflist]);
                //  MembersKeys memberkey =
                //      new MembersKeys(memID);
                memberFactory = new MembersFactory();
                //get member of level i
                Members memberlocal = new Members();
                memberlocal = memberFactory.GetByPrimaryKey(memID);

                //get value of level
                int ilevelvalue = Integer.parseInt(ruleList.get(ilevels - 1).getRuleValue().toString());
                //int ilevelvalue = 1;

                /*Core for compute commission. If member has full child, system will add score
                 * into Avaible. Otherwise. System will add into hide score or avaible score.
                 * if member has just been add is the second child. System will add core and hide score into avaible score and reject hide score
                 */
                if (checkFullChild(memberlocal)) {
                    //    if (true) {
                    int avaiable = memberlocal.getAvaiableScore().intValue() + ilevelvalue + memberlocal.getHideScore().intValue();
                    //memberlocal.AvaiableScore = memberlocal.AvaiableScore + ilevelvalue + memberlocal.HideScore;
                    memberlocal.setAvaiableScore(BigInteger.valueOf(avaiable));
                    memberlocal.setHideScore(BigInteger.ZERO);
                } else {
                    if (ilevels == 1) {
                        int avaiable_temp1 = memberlocal.getAvaiableScore().intValue() + ilevelvalue;
                        //memberlocal.AvaiableScore = memberlocal.AvaiableScore + ilevelvalue;
                        memberlocal.setAvaiableScore(BigInteger.valueOf(avaiable_temp1));
                        if (memberlocal.getHideScore().intValue() > 0) {
                            int avaible_temp2 = memberlocal.getAvaiableScore().intValue() + memberlocal.getHideScore().intValue();
                            //memberlocal.AvaiableScore = memberlocal.AvaiableScore + memberlocal.HideScore;
                            memberlocal.setAvaiableScore(BigInteger.valueOf(avaible_temp2));
                            memberlocal.setHideScore(BigInteger.ZERO);
                        }
                    } else {
                        int hidescore = memberlocal.getHideScore().intValue() + ilevelvalue;
                        //memberlocal.HideScore = memberlocal.HideScore + ilevelvalue;
                        memberlocal.setHideScore(BigInteger.valueOf(hidescore));
                    }
                }

                //Declare report variable
                Reports report = new Reports();
                report.setMemIdRev(memberlocal.getMemId());
                report.setMemIdSend(member.getMemId());
                report.setCommission(BigInteger.valueOf(ilevelvalue));
                report.setDate(member.getDateReg());

                memberFactory = new MembersFactory();
                reportsFactory = new ReportsFactory();
                //Update into Members table and Reports table
                memberFactory.Update(memberlocal);
                reportsFactory.Insert(report);

                //Set value for variable run list and levels
                iLenghtOflist = iLenghtOflist - 1;
                ilevels = ilevels + 1;
            }
        } catch (Exception ex) {
        }
    }

    public static Boolean checkFullChild(Members member) {
        List<Members> members = new ArrayList<Members>();
        MembersFactory memberFactory = new MembersFactory();
        members = memberFactory.GetNameSpace(member.getNameSpace());

        int childLevel = member.getNameSpace().split("\\.").length + 1;
        int countChildren = 0;

//        var childList = members.Where(m = >
//                 m.NameSpace.Count(c = >  c.Equals('.')) == (member.NameSpace.Count(c = >  c.Equals('.')) + 1));

        for (int i = 0; i < members.size(); i++) {
            if (members.get(i).getNameSpace().split("\\.").length == childLevel) {
                countChildren++;
            }
        }

        if (countChildren < 2) {
            return false;
        } else if (countChildren >= 2) {
            return true;
        } else {
            return false;
        }
    }
}
